home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / mac / files / t_sys5 / unixcpio.gz / unixnet.cpio / cmdparse.c < prev    next >
C/C++ Source or Header  |  1994-07-11  |  5KB  |  211 lines

  1. /* Parse command line, set up command arguments Unix-style, and call function.
  2.  * Note: argument is modified (delimiters are overwritten with nulls)
  3.  * Improved error handling by Brian Boesch of Stanford University
  4.  */
  5. #include <stdio.h>
  6. #include <ctype.h>
  7. #ifdef    UNIX
  8. #undef    toupper
  9. #undef    tolower
  10. #endif
  11. #include "global.h"
  12. #include "cmdparse.h"
  13.  
  14. int
  15. cmdparse(cmds,line)
  16. struct cmds cmds[];
  17. register char *line;
  18. {
  19.     register struct cmds *cmdp;
  20.     char *argv[NARG],*cp,*pp,*vp,*ep,*rp,*getenv();
  21.     static char pool[POOLSIZE];
  22.     int argc,quote;
  23.     int rslt;
  24.  
  25.     /* Remove cr/lf */
  26.     rip(line);
  27.  
  28.     for(argc = 0;argc < NARG;argc++)
  29.         argv[argc] = NULLCHAR;
  30.  
  31.     pp = pool;
  32.  
  33.     for(argc = 0;argc < NARG && *line != '\0';){
  34.         quote = 0;
  35.         /* Skip leading white space */
  36.         while(*line == ' ' || *line == '\t')
  37.         line++;
  38.         if(*line == '\0')
  39.         break;
  40.         /* Check for quoted token */
  41.         if(*line == '"' || *line == '\'')
  42.         quote = *line++;    /* Suppress quote, remember it */
  43.         argv[argc++] = line;    /* Beginning of token */
  44.         /* Find terminating delimiter */
  45.         if(quote){
  46.         /* Find quote, it must be present */
  47.         if((line = index(line,quote)) == NULLCHAR)
  48.             return -1;
  49.  
  50.         *line++ = '\0';
  51.         } else {
  52.         /* Find space or tab. If not present,
  53.          * then we've already found the last
  54.          * token.
  55.          */
  56.         for (cp = line; *cp; cp++)
  57.             if (*cp == ' ' || *cp == '\t')
  58.             break;
  59.         if (*cp != '\0')
  60.             *cp++ = '\0';
  61.         line = cp;
  62.         }
  63.         /* Check for variablename */
  64.         if(quote != '\'' && index(cp = argv[argc - 1],'$') != NULLCHAR){
  65.         argv[argc - 1] = pp;
  66.         while (*cp != '\0') {
  67.             if (*cp != '$')
  68.             *pp++ = *cp++;
  69.             else {
  70.             if (*++cp == '{') {
  71.                 if ((ep = index(++cp,'}')) == NULLCHAR)
  72.                 return -1;
  73.                 *ep++ = '\0';
  74.             } else {
  75.                 ep = NULLCHAR;
  76.             }
  77.             /* Scan to end of varname and mark it */
  78.             for (vp = cp; isalnum(*vp) || *vp == '_'; vp++)
  79.                 *vp = toupper(*vp);
  80.             /* If a name found, get value */
  81.             if (vp != cp){
  82.                 rslt = *vp;            /* save next and make \0 */
  83.                 *vp = '\0';
  84.                 rp = getenv(cp);
  85.                 *vp = rslt;            /* restore next character */
  86.                 if (ep == NULLCHAR){    /* no braces */
  87.                 if (rp == NULLCHAR)    /* undef'd var */
  88.                     rp = "";        /* then just empty */
  89.                 } else {
  90.                 if (rp == NULLCHAR)    /* undef'd var */
  91.                     switch (rslt) {    /* else look at next */
  92. /*                    case '=': */
  93. /*                    dosetenv(2,(&cp)-1);/* assign and subst */
  94.                     case '-':
  95.                     rp = vp + 1;    /* subst next word */
  96.                     break;
  97.                     case '?':
  98.                     if (*++vp == '\0')
  99.                     vp = "undefined variable";
  100.                     printf("%s\n",vp);
  101.                     return -1;
  102.                     default:
  103.                     rp = "";    /* default is empty */
  104.                     }
  105.                 else
  106.                     if (rslt == '+')    /* defined and subst */
  107.                     rp = vp + 1;
  108.                 }
  109.                 /* Copy the result to the pool */
  110.                 while (*pp++ = *rp++)
  111.                 ;
  112.                 pp--;
  113.                 cp = vp;
  114.             }
  115.             if (ep != NULLCHAR)
  116.                 cp = ep;
  117.             }
  118.         }
  119.         *pp++ = '\0';
  120.         if (pp > pool + POOLSIZE){    /* check pool overflow */
  121.             printf("panic: pool overflow\n");
  122.             fflush(stdout);
  123.             for (;;)            /* dangerous to continue */
  124.             ;
  125.         }
  126.         }
  127.     }
  128.     if (argc < 1) {        /* empty command line */
  129.         argc = 1;
  130.         argv[0] = "";
  131.     }
  132.     /* Lines beginning with "#" are comments */
  133.     if(argv[0][0] == '#')
  134.         return 0;
  135.  
  136.     /* Look up command in table; prefix matches are OK */
  137.     for(cmdp = cmds;cmdp->name != NULLCHAR;cmdp++){
  138.         if(strncmp(argv[0],cmdp->name,strlen(argv[0])) == 0)
  139.             break;
  140.     }
  141.     if(cmdp->name == NULLCHAR) {
  142.         if(cmdp->argc_errmsg != NULLCHAR)
  143.             printf("%s\n",cmdp->argc_errmsg);
  144.         return -1;
  145.     } else {
  146.         if(argc < cmdp->argcmin) {
  147.             /* Insufficient arguments */
  148.                 printf("Usage: %s\n",cmdp->argc_errmsg); 
  149.             return -1;
  150.         } else {
  151.             argv[0] = cmdp->name;
  152.             rslt = (*cmdp->func)(argc,argv);
  153.             if ((rslt < 0) && (cmdp->exec_errmsg != NULLCHAR))
  154.                 printf("%s\n",cmdp->exec_errmsg);
  155.             return(rslt);
  156.         }
  157.     }
  158. }
  159.  
  160. /* Call a subcommand based on the first token in an already-parsed line */
  161. int
  162. subcmd(tab,argc,argv)
  163. struct cmds tab[];
  164. int argc;
  165. char *argv[];
  166. {
  167.     int rslt,len;
  168.     register struct cmds *cmdp;
  169.  
  170.     /* Strip off first token and pass rest of line to subcommand */
  171.     if (argc < 2) {
  172.         if (argc < 1)
  173.             printf("SUBCMD - Don't know what to do?\n");
  174.         else
  175.             printf("\"%s\" - takes at least one argument\n",argv[0]);
  176.         return -1;
  177.     }
  178.     for(cmdp = tab;cmdp->name != NULLCHAR;cmdp++){
  179.         if(strncmp(argv[1],cmdp->name,strlen(argv[1])) == 0){
  180.             if(--argc < cmdp->argcmin) {
  181.                 if (cmdp->argc_errmsg != NULLCHAR)
  182.                     printf("Usage: %s\n",cmdp->argc_errmsg); 
  183.                 return -1;
  184.             } else {
  185.                 (++argv)[0] = cmdp->name;
  186.                 rslt = (*cmdp->func)(argc,argv);
  187.                 if ((rslt < 0) && (cmdp->exec_errmsg != NULLCHAR))
  188.                     printf("%s\n",cmdp->exec_errmsg);
  189.                 return(rslt);
  190.             }
  191.         }
  192.     }
  193.     if (cmdp->argc_errmsg != NULLCHAR){
  194.         if (cmdp->argc_errmsg[0] != '?'){
  195.             printf("%s\n",cmdp->argc_errmsg);
  196.         } else {
  197.             printf("%s %s:",argv[0],cmdp->argc_errmsg + 1);
  198.             len = strlen(argv[0]) + strlen(cmdp->argc_errmsg) + 1;
  199.             for(cmdp = tab;cmdp->name != NULLCHAR;cmdp++){
  200.                 if ((len += strlen(cmdp->name) + 1) > 79){
  201.                     len = strlen(cmdp->name) + 9;
  202.                     printf("\n        ");
  203.                 }
  204.                 printf(" %s",cmdp->name);
  205.             }
  206.             printf("\n");
  207.         }
  208.     }
  209.     return -1;
  210. }
  211.